﻿namespace Atomic.Plugins
{
    using System;
    using System.IO;
    using System.Text;
    using System.Linq;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.Hosting;

    using Atomic.Extensions;
    using Atomic.Plugins.Files;

    /// <summary>
    /// 插件获得程序。
    /// </summary>
    public class PluginHarvester : IPluginHarvester
    {
        /// <summary>
        /// 虚拟路径提供程序。
        /// </summary>
        private readonly IVirtualPathProvider _virtualPathProvider = null;

        /// <summary>
        /// 清单文件管理器。
        /// </summary>
        private readonly IManifestManager _manifestManager = null;

        /// <summary>
        /// 初始化插件获得程序。
        /// </summary>
        /// <param name="virtualPathProvider">虚拟路径提供程序。</param>
        /// <param name="manifestManager">清单文件管理器。</param>
        public PluginHarvester(IVirtualPathProvider virtualPathProvider, IManifestManager manifestManager)
        {
            this._virtualPathProvider = virtualPathProvider;
            this._manifestManager = manifestManager;
        }

        /// <summary>
        /// 获得插件集合。
        /// </summary>
        /// <remarks>
        /// 例：
        /// Name:内容模块
        /// version:1.0
        /// description:用于处理文章信息。
        /// website:http://www.atomic.com
        /// author:cjnmy36723
        /// assembly:Staroce.Contents.dll
        /// ----------------------------------
        /// 其中：assembly 节点是必要的。
        /// 建议“Name”，“version”，“description”，“author”，“assembly”都要填写。
        /// </remarks>
        /// <param name="paths">插件根目录集合。</param>
        /// <param name="manifestName">插件描述的文件名。</param>
        /// <returns>插件集合。</returns>
        public IEnumerable<PluginDescriptor> HarvestPlugins(IEnumerable<string> paths, string manifestName)
        {
            return paths.SelectMany(path => this.HarvestPlugins(path, manifestName)).ToList();
        }

        /// <summary>
        /// 获得插件集合。
        /// </summary>
        /// <param name="path">插件根目录。</param>
        /// <param name="manifestName">插件描述的文件名。</param>
        /// <returns>插件集合。</returns>
        private IEnumerable<PluginDescriptor> HarvestPlugins(string path, string manifestName)
        {
            //缓存 KEY。
            string key = string.Format("{0}-{1}", path, manifestName);

            return AvailablePluginInFolder(path, manifestName).ToReadOnlyCollection();
        }

        /// <summary>
        /// 获得指定的目录下可用的插件描述集合。
        /// </summary>
        /// <param name="path">插件根目录。</param>
        /// <param name="manifestName">插件描述的文件名。</param>
        /// <returns>插件描述集合。</returns>
        private List<PluginDescriptor> AvailablePluginInFolder(string path, string manifestName)
        {
            //插件目录列表。
            var subfolderPaths = this._virtualPathProvider.ListDirectories(path);

            var localList = new List<PluginDescriptor>();
            
            foreach (var subfolderPath in subfolderPaths)
            {
                //插件标识。
                var pluginId = Path.GetFileName(subfolderPath.TrimEnd('/', '\\'));

                //插件配置清单。
                var manifestPath = Path.Combine(subfolderPath, manifestName);

                //获得插件描述信息。
                var descriptor = this._manifestManager.GetPluginDescriptor(pluginId, path, manifestPath);

                if (descriptor == null)
                    continue;

                localList.Add(descriptor);
            }

            return localList;
        }
    }
}